//
// Created by casdon on 2024/8/1.
//

#ifndef CIOT_WLAN_H
#define CIOT_WLAN_H

#include "types.h"
//#include <ciot/private/preference.h>

#ifdef __cplusplus
extern "C" {
#endif

//////////////
#define PreferenceDef( ID, Props ) \
typedef struct Preference##ID##_t\
{\
char *name;\
char *description;\
char *version;\
uint32_t  createtime;\
uint32_t  lasttime;\
Props \
} Preference##ID;


PreferenceDef(Clink,
    char * wifissid;
    char * wifipass;
    bool clinkSucceed;
);

#define PreferenceKeyDef( ID, keys... ) \
typedef enum Preference##ID##Key_e \
{\
    ID##PrefKey_name,\
    ID##PrefKey_description,\
    ID##PrefKey_version,\
    ID##PrefKey_createtime,\
    ID##PrefKey_lasttime,\
    keys \
} Preference##ID##Key;

PreferenceKeyDef(Clink,
    ClinkPrefKey_wifissid,
    ClinkPrefKey_wifipass,
    ClinkPrefKey_clinkSucceed
);
//////////////

#define CIOT_WLAN_MAX_RECONNECT_TIMES 4
#define CIOT_WLAN_STA_FAST_FAILED_DURATION 4000

typedef enum Ciot_sta_status_e
{
    Ciot_sta_status_idle = 0,
    Ciot_sta_status_ready,
    Ciot_sta_status_waiting_connect,
    Ciot_sta_status_connecting,
    Ciot_sta_status_dhcp,
    Ciot_sta_status_connected,
    Ciot_sta_status_timeout,
    Ciot_sta_status_failed,
    Ciot_sta_status_password_wrong,

    Ciot_sta_status_MAX
} Ciot_sta_status;

typedef struct ciot_sta_connection_status_t
{
    char ip[16];
    int ipLen;
    int rssi;
    int signalStr;
    int channel;
    Ciot_sta_status status;

} Ciot_sta_connection_status;

typedef struct ciot_wlan_ap_config_t
{
    uint8_t ssid[31];
    uint8_t ssid_len;
    uint8_t pass[31];
    uint8_t pass_len;
    uint8_t channel;
} ciot_wlan_ap_config;

typedef enum Ciot_wlan_mode_support_e
{
    Ciot_wlan_mode_not_supported = 0,
    Ciot_wlan_mode_sta_only,
    Ciot_wlan_mode_mutex_ap_sta,
    Ciot_wlan_mode_coexist_ap_sta,

    Ciot_wlan_mode_MAX
} Ciot_wlan_mode_support;

typedef struct Ciot_wlan_router_info_t
{
    char ssid[64];
    char mac[20];
    bool enc;
    int  str; //  0-5

} Ciot_wlan_router_info;


typedef struct Ciot_wlan_connection_status_t{
    char ssid[128];
    int ssidLen;
    char ip[16];
    int ipLen;
    int rssi;
    int signalStr;
    int channel;
    Ciot_sta_status status;
} Ciot_wlan_connection_status;

typedef struct ciot_clink_key_data_t {
    union {
        bool bool_v;
        char *string_v;
    };
    Ciot_product_data_type type;

    /**
     * Must specific when use  string, raw types
     */
    uint16_t len;

} ciot_clink_key_data;

typedef void (*CiotWifiStatusUpdateNotify) ( Ciot_wlan_connection_status * status );
typedef void (*CiotWifiScanResultNotify) ( Ciot_wlan_router_info ** routers, int total );

typedef struct ciot_wlan_adapter_manager_t
{
    bool inited;
    CIOT_ADAPTER    Ciot_res (* init)(void);
    CIOT_ADAPTER    Ciot_res (* deinit)(void);

    // Important for feedback to APP on SoftAP mode
    CIOT_ADAPTER    bool (* sta_ap_bridge_supported) ();

    // Wi-Fi
    // (STA)
    // ssid, pass end with \0
    CIOT_ADAPTER    Ciot_res (* connect_sta) ( const char * ssid, const char * pass );
    CIOT_ADAPTER    Ciot_res (* reconnect_sta) (void);
    CIOT_ADAPTER    Ciot_res (* disconnect_sta) (void);
    CIOT_PRIVATE    Ciot_res (* force_disconnect_sta) (void);
    CIOT_ADAPTER    Ciot_res (* sta_check_connection_status ) ( Ciot_sta_connection_status * status );

    CIOT_EVENT      Ciot_res (* sta_connected) (void);
    CIOT_EVENT      Ciot_res (* sta_disconnected) (void);
    CIOT_EVENT      Ciot_res (* sta_failed) ( Ciot_sta_status status );
    CIOT_EVENT      Ciot_res (* sta_status_update) ( Ciot_sta_connection_status * status );

    // (AP)
    // Less than 32 char
    // ssid, pass end with \0
    CIOT_ADAPTER    Ciot_res (* start_ap)( const ciot_wlan_ap_config * config );
    CIOT_ADAPTER    Ciot_res (* stop_ap)();
    CIOT_ADAPTER    bool (* is_start_ap)();//是否启动AP
    CIOT_ADAPTER    Ciot_res (* start_ap_succeed)();//是否启动AP成功
#if !CIOT_MINI_VERSION && !CIOT_SDK_FOR_HOST && !CIOT_SDK_FOR_MOBILE
    CIOT_ADAPTER    ciot_clink_key_data (* flash_read_config)( PreferenceClinkKey key );
    CIOT_ADAPTER    Ciot_res (* flash_save_config)( PreferenceClinkKey key, ciot_clink_key_data data );
    CIOT_ADAPTER    Ciot_res (* flash_erase_config)( uint8_t * buf, uint32_t len );
#endif
    CIOT_ADAPTER    Ciot_res (* scan) ( CiotWifiScanResultNotify resCB );
    CIOT_API        Ciot_res (* watch_wifi_status) ( CiotWifiStatusUpdateNotify statusUpdateCB );

} ciot_wlan_adapter_manager;

extern Ciot_res ciot_porting_wlan_init();

CIOT_API
Ciot_res ciot_wlan_adapter_manager_reg( ciot_wlan_adapter_manager * wlan_adapter, Ciot_wlan_mode_support supportedMode );

CIOT_API
const ciot_wlan_adapter_manager * ciot_wlan_adapter_manager_instance();

#define ciot_wlan_reg(A,B) ciot_wlan_adapter_manager_reg(A,B)
#define ciot_wlan_mgr() ciot_wlan_adapter_manager_instance()
#define ciot_wlan() ciot_wlan_mgr()

#ifdef __cplusplus
}
#endif

#endif //CIOT_WLAN_H
